import { defineComponent, isVNode, ref, reactive, computed, watch, nextTick, onMounted, onBeforeUnmount, resolveComponent, resolveDirective, openBlock, createBlock, Transition, withCtx, withDirectives, createVNode, withModifiers, createCommentVNode, toDisplayString, withKeys, renderSlot, vShow, createTextVNode, render as render$1, h } from 'vue';
import ElButton from '../el-button';
import ElInput from '../el-input';
import { t } from '../locale';
import { Overlay } from '../el-overlay';
import { useModal, usePreventGlobal, useLockScreen, useRestoreActive } from '../hooks';
import { TrapFocus } from '../directives';
import PopupManager from '../utils/popup-manager';
import { on, off } from '../utils/dom';
import { isString, isVNode as isVNode$1 } from '../utils/util';
import { EVENT_CODE } from '../utils/aria';
import isServer from '../utils/isServer';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

const TypeMap = {
    success: 'success',
    info: 'info',
    warning: 'warning',
    error: 'error',
};
var script = defineComponent({
    name: 'ElMessageBox',
    components: {
        ElButton,
        ElInput,
        ElOverlay: Overlay,
    },
    directives: {
        TrapFocus,
    },
    props: {
        beforeClose: {
            type: Function,
            default: undefined,
        },
        callback: Function,
        cancelButtonText: {
            type: String,
        },
        cancelButtonClass: String,
        center: Boolean,
        closeOnClickModal: {
            type: Boolean,
            default: true,
        },
        closeOnPressEscape: {
            type: Boolean,
            default: true,
        },
        closeOnHashChange: {
            type: Boolean,
            default: true,
        },
        confirmButtonText: {
            type: String,
        },
        confirmButtonClass: String,
        container: {
            type: String,
            default: 'body',
        },
        customClass: String,
        dangerouslyUseHTMLString: Boolean,
        distinguishCancelAndClose: Boolean,
        iconClass: String,
        inputPattern: {
            type: Object,
            default: () => undefined,
            validator: (val) => (val instanceof RegExp || val === 'undefined'),
        },
        inputPlaceholder: {
            type: String,
        },
        inputType: {
            type: String,
            default: 'text',
        },
        inputValue: {
            type: String,
        },
        inputValidator: {
            type: Function,
            default: null,
        },
        inputErrorMessage: String,
        lockScroll: {
            type: Boolean,
            default: true,
        },
        message: {
            type: [String, Object],
            validator: (val) => {
                return isString(val) || isVNode(val);
            },
        },
        modalFade: {
            type: Boolean,
            default: true,
        },
        modalClass: String,
        modal: {
            type: Boolean,
            default: true,
        },
        roundButton: Boolean,
        showCancelButton: Boolean,
        showConfirmButton: {
            type: Boolean,
            default: true,
        },
        showClose: {
            type: Boolean,
            default: true,
        },
        type: String,
        title: String,
        showInput: Boolean,
        zIndex: Number,
    },
    emits: ['vanish', 'action'],
    setup(props, { emit }) {
        const visible = ref(false);
        const state = reactive({
            action: '',
            inputValue: props.inputValue,
            confirmButtonLoading: false,
            cancelButtonLoading: false,
            cancelButtonText: props.cancelButtonText,
            confirmButtonDisabled: false,
            confirmButtonText: props.confirmButtonText,
            editorErrorMessage: '',
            validateError: false,
            zIndex: PopupManager.nextZIndex(),
        });
        const icon = computed(() => props.iconClass || (props.type && TypeMap[props.type] ? `el-icon-${TypeMap[props.type]}` : ''));
        const hasMessage = computed(() => !!props.message);
        const inputRef = ref(null);
        const confirmRef = ref(null);
        const confirmButtonClasses = computed(() => `el-button--primary ${props.confirmButtonClass}`);
        watch(() => state.inputValue, (val) => __awaiter(this, void 0, void 0, function* () {
            yield nextTick();
            if (props.type === 'prompt' && val !== null) {
                validate();
            }
        }), { immediate: true });
        watch(() => visible.value, val => {
            if (val) {
                if (props.type === 'alert' || props.type === 'confirm') {
                    nextTick().then(() => { var _a, _b, _c; (_c = (_b = (_a = confirmRef.value) === null || _a === void 0 ? void 0 : _a.$el) === null || _b === void 0 ? void 0 : _b.focus) === null || _c === void 0 ? void 0 : _c.call(_b); });
                }
                state.zIndex = PopupManager.nextZIndex();
            }
            if (props.type !== 'prompt')
                return;
            if (val) {
                nextTick().then(() => {
                    if (inputRef.value && inputRef.value.$el) {
                        getInputElement().focus();
                    }
                });
            }
            else {
                state.editorErrorMessage = '';
                state.validateError = false;
            }
        });
        onMounted(() => __awaiter(this, void 0, void 0, function* () {
            yield nextTick();
            if (props.closeOnHashChange) {
                on(window, 'hashchange', doClose);
            }
        }));
        onBeforeUnmount(() => {
            if (props.closeOnHashChange) {
                off(window, 'hashchange', doClose);
            }
        });
        function doClose() {
            if (!visible.value)
                return;
            visible.value = false;
            nextTick(() => {
                if (state.action)
                    emit('action', state.action);
            });
        }
        const handleWrapperClick = () => {
            if (props.closeOnClickModal) {
                handleAction(props.distinguishCancelAndClose ? 'close' : 'cancel');
            }
        };
        const handleInputEnter = () => {
            if (props.inputType !== 'textarea') {
                return handleAction('confirm');
            }
        };
        const handleAction = (action) => {
            var _a;
            if (props.type === 'prompt' && action === 'confirm' && !validate()) {
                return;
            }
            state.action = action;
            if (props.beforeClose) {
                (_a = props.beforeClose) === null || _a === void 0 ? void 0 : _a.call(props, action, state, doClose);
            }
            else {
                doClose();
            }
        };
        const validate = () => {
            if (props.type === 'prompt') {
                const inputPattern = props.inputPattern;
                if (inputPattern && !inputPattern.test(state.inputValue || '')) {
                    state.editorErrorMessage = props.inputErrorMessage || t('el.messagebox.error');
                    state.validateError = true;
                    return false;
                }
                const inputValidator = props.inputValidator;
                if (typeof inputValidator === 'function') {
                    const validateResult = inputValidator(state.inputValue);
                    if (validateResult === false) {
                        state.editorErrorMessage = props.inputErrorMessage || t('el.messagebox.error');
                        state.validateError = true;
                        return false;
                    }
                    if (typeof validateResult === 'string') {
                        state.editorErrorMessage = validateResult;
                        state.validateError = true;
                        return false;
                    }
                }
            }
            state.editorErrorMessage = '';
            state.validateError = false;
            return true;
        };
        const getInputElement = () => {
            const inputRefs = inputRef.value.$refs;
            return (inputRefs.input || inputRefs.textarea);
        };
        const handleClose = () => {
            handleAction('close');
        };
        if (props.closeOnPressEscape) {
            useModal({
                handleClose,
            }, visible);
        }
        else {
            usePreventGlobal(visible, 'keydown', (e) => e.code === EVENT_CODE.esc);
        }
        if (props.lockScroll) {
            useLockScreen(visible);
        }
        useRestoreActive(visible);
        return {
            state,
            visible,
            hasMessage,
            icon,
            confirmButtonClasses,
            inputRef,
            confirmRef,
            doClose,
            handleClose,
            handleWrapperClick,
            handleInputEnter,
            handleAction,
            t,
        };
    },
});

const _hoisted_1 = {
  key: 0,
  class: "el-message-box__header"
};
const _hoisted_2 = { class: "el-message-box__title" };
const _hoisted_3 = /*#__PURE__*/createVNode("i", { class: "el-message-box__close el-icon-close" }, null, -1 /* HOISTED */);
const _hoisted_4 = { class: "el-message-box__content" };
const _hoisted_5 = { class: "el-message-box__container" };
const _hoisted_6 = {
  key: 1,
  class: "el-message-box__message"
};
const _hoisted_7 = { key: 0 };
const _hoisted_8 = { class: "el-message-box__input" };
const _hoisted_9 = { class: "el-message-box__btns" };

function render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_el_input = resolveComponent("el-input");
  const _component_el_button = resolveComponent("el-button");
  const _component_el_overlay = resolveComponent("el-overlay");
  const _directive_trap_focus = resolveDirective("trap-focus");

  return (openBlock(), createBlock(Transition, {
    name: "fade-in-linear",
    onAfterLeave: _cache[8] || (_cache[8] = $event => (_ctx.$emit('vanish')))
  }, {
    default: withCtx(() => [
      withDirectives(createVNode(_component_el_overlay, {
        "z-index": _ctx.state.zIndex,
        "overlay-class": ['is-message-box', _ctx.modalClass],
        mask: _ctx.modal,
        onClick: withModifiers(_ctx.handleWrapperClick, ["self"])
      }, {
        default: withCtx(() => [
          withDirectives(createVNode("div", {
            ref: "root",
            "aria-label": _ctx.title || 'dialog',
            "aria-modal": "true",
            class: [
          'el-message-box',
          _ctx.customClass,
          { 'el-message-box--center': _ctx.center },
        ]
          }, [
            (_ctx.title !== null && _ctx.title !== undefined)
              ? (openBlock(), createBlock("div", _hoisted_1, [
                  createVNode("div", _hoisted_2, [
                    (_ctx.icon && _ctx.center)
                      ? (openBlock(), createBlock("div", {
                          key: 0,
                          class: ['el-message-box__status', _ctx.icon]
                        }, null, 2 /* CLASS */))
                      : createCommentVNode("v-if", true),
                    createVNode("span", null, toDisplayString(_ctx.title), 1 /* TEXT */)
                  ]),
                  (_ctx.showClose)
                    ? (openBlock(), createBlock("button", {
                        key: 0,
                        type: "button",
                        class: "el-message-box__headerbtn",
                        "aria-label": "Close",
                        onClick: _cache[1] || (_cache[1] = $event => (
              _ctx.handleAction(_ctx.distinguishCancelAndClose ? 'close' : 'cancel')
            )),
                        onKeydown: _cache[2] || (_cache[2] = withKeys($event => (
              _ctx.handleAction(_ctx.distinguishCancelAndClose ? 'close' : 'cancel')
            ), ["enter"]))
                      }, [
                        _hoisted_3
                      ], 32 /* HYDRATE_EVENTS */))
                    : createCommentVNode("v-if", true)
                ]))
              : createCommentVNode("v-if", true),
            createVNode("div", _hoisted_4, [
              createVNode("div", _hoisted_5, [
                (_ctx.icon && !_ctx.center && _ctx.hasMessage)
                  ? (openBlock(), createBlock("div", {
                      key: 0,
                      class: ['el-message-box__status', _ctx.icon]
                    }, null, 2 /* CLASS */))
                  : createCommentVNode("v-if", true),
                (_ctx.hasMessage)
                  ? (openBlock(), createBlock("div", _hoisted_6, [
                      renderSlot(_ctx.$slots, "default", {}, () => [
                        (!_ctx.dangerouslyUseHTMLString)
                          ? (openBlock(), createBlock("p", _hoisted_7, toDisplayString(_ctx.message), 1 /* TEXT */))
                          : (openBlock(), createBlock("p", {
                              key: 1,
                              innerHTML: _ctx.message
                            }, null, 8 /* PROPS */, ["innerHTML"]))
                      ])
                    ]))
                  : createCommentVNode("v-if", true)
              ]),
              withDirectives(createVNode("div", _hoisted_8, [
                createVNode(_component_el_input, {
                  ref: "inputRef",
                  modelValue: _ctx.state.inputValue,
                  "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => (_ctx.state.inputValue = $event)),
                  type: _ctx.inputType,
                  placeholder: _ctx.inputPlaceholder,
                  class: { invalid: _ctx.state.validateError },
                  onKeydown: withKeys(withModifiers(_ctx.handleInputEnter, ["prevent"]), ["enter"])
                }, null, 8 /* PROPS */, ["modelValue", "type", "placeholder", "class", "onKeydown"]),
                createVNode("div", {
                  class: "el-message-box__errormsg",
                  style: {
                visibility: !!_ctx.state.editorErrorMessage ? 'visible' : 'hidden',
              }
                }, toDisplayString(_ctx.state.editorErrorMessage), 5 /* TEXT, STYLE */)
              ], 512 /* NEED_PATCH */), [
                [vShow, _ctx.showInput]
              ])
            ]),
            createVNode("div", _hoisted_9, [
              (_ctx.showCancelButton)
                ? (openBlock(), createBlock(_component_el_button, {
                    key: 0,
                    loading: _ctx.state.cancelButtonLoading,
                    class: [_ctx.cancelButtonClass],
                    round: _ctx.roundButton,
                    size: "small",
                    onClick: _cache[4] || (_cache[4] = $event => (_ctx.handleAction('cancel'))),
                    onKeydown: _cache[5] || (_cache[5] = withKeys($event => (_ctx.handleAction('cancel')), ["enter"]))
                  }, {
                    default: withCtx(() => [
                      createTextVNode(toDisplayString(_ctx.state.cancelButtonText || _ctx.t('el.messagebox.cancel')), 1 /* TEXT */)
                    ]),
                    _: 1 /* STABLE */
                  }, 8 /* PROPS */, ["loading", "class", "round"]))
                : createCommentVNode("v-if", true),
              withDirectives(createVNode(_component_el_button, {
                ref: "confirmRef",
                loading: _ctx.state.confirmButtonLoading,
                class: [_ctx.confirmButtonClasses],
                round: _ctx.roundButton,
                disabled: _ctx.state.confirmButtonDisabled,
                size: "small",
                onClick: _cache[6] || (_cache[6] = $event => (_ctx.handleAction('confirm'))),
                onKeydown: _cache[7] || (_cache[7] = withKeys($event => (_ctx.handleAction('confirm')), ["enter"]))
              }, {
                default: withCtx(() => [
                  createTextVNode(toDisplayString(_ctx.state.confirmButtonText || _ctx.t('el.messagebox.confirm')), 1 /* TEXT */)
                ]),
                _: 1 /* STABLE */
              }, 8 /* PROPS */, ["loading", "class", "round", "disabled"]), [
                [vShow, _ctx.showConfirmButton]
              ])
            ])
          ], 10 /* CLASS, PROPS */, ["aria-label"]), [
            [_directive_trap_focus]
          ])
        ]),
        _: 1 /* STABLE */
      }, 8 /* PROPS */, ["z-index", "overlay-class", "mask", "onClick"]), [
        [vShow, _ctx.visible]
      ])
    ]),
    _: 1 /* STABLE */
  }))
}

script.render = render;
script.__file = "packages/message-box/src/index.vue";

const messageInstance = new Map();
const initInstance = (props, container) => {
    const vnode = h(script, props);
    render$1(vnode, container);
    document.body.appendChild(container.firstElementChild);
    return vnode.component;
};
const genContainer = () => {
    return document.createElement('div');
};
const showMessage = (options) => {
    const container = genContainer();
    options.onVanish = () => {
        render$1(null, container);
        messageInstance.delete(vm);
    };
    options.onAction = (action) => {
        const currentMsg = messageInstance.get(vm);
        let resolve;
        if (options.showInput) {
            resolve = { value: vm.state.inputValue, action };
        }
        else {
            resolve = action;
        }
        if (options.callback) {
            options.callback(resolve, instance.proxy);
        }
        else {
            if (action === 'cancel' || action === 'close') {
                if (options.distinguishCancelAndClose && action !== 'cancel') {
                    currentMsg.reject('close');
                }
                else {
                    currentMsg.reject('cancel');
                }
            }
            else {
                currentMsg.resolve(resolve);
            }
        }
    };
    const instance = initInstance(options, container);
    const vm = instance.proxy;
    if (isVNode$1(options.message)) {
        instance.slots.default = () => [options.message];
    }
    vm.visible = true;
    return vm;
};
function MessageBox(options) {
    if (isServer)
        return;
    let callback;
    if (isString(options) || isVNode$1(options)) {
        options = {
            message: options,
        };
    }
    else {
        callback = options.callback;
    }
    return new Promise((resolve, reject) => {
        const vm = showMessage(options);
        messageInstance.set(vm, {
            options,
            callback,
            resolve,
            reject,
        });
    });
}
MessageBox.alert = (message, title, options) => {
    if (typeof title === 'object') {
        options = title;
        title = '';
    }
    else if (title === undefined) {
        title = '';
    }
    return MessageBox(Object.assign({
        title: title,
        message: message,
        type: 'alert',
        closeOnPressEscape: false,
        closeOnClickModal: false,
    }, options));
};
MessageBox.confirm = (message, title, options) => {
    if (typeof title === 'object') {
        options = title;
        title = '';
    }
    else if (title === undefined) {
        title = '';
    }
    return MessageBox(Object.assign({
        title: title,
        message: message,
        type: 'confirm',
        showCancelButton: true,
    }, options));
};
MessageBox.prompt = (message, title, options) => {
    if (typeof title === 'object') {
        options = title;
        title = '';
    }
    else if (title === undefined) {
        title = '';
    }
    return MessageBox(Object.assign({
        title: title,
        message: message,
        showCancelButton: true,
        showInput: true,
        type: 'prompt',
    }, options));
};
MessageBox.close = () => {
    messageInstance.forEach((_, vm) => {
        vm.doClose();
    });
    messageInstance.clear();
};

const _MessageBox = MessageBox;
_MessageBox.install = app => {
    app.config.globalProperties.$msgbox = _MessageBox;
    app.config.globalProperties.$messageBox = _MessageBox;
    app.config.globalProperties.$alert = _MessageBox.alert;
    app.config.globalProperties.$confirm = _MessageBox.confirm;
    app.config.globalProperties.$prompt = _MessageBox.prompt;
};

export default _MessageBox;
